﻿using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Top100BoxML
{
    public partial class Top100MusicDownload : Form
    {
        public Top100MusicDownload()
        {
            InitializeComponent();
        }

        private const string FP_ART_INFO = "ArtInfos.csv";
        private const char FG_VALUE = '┏';
        private const string ID_CATCH_HEAD_STRING = "id%3D";

        private string m_CurrSongPageUrl = "";

        private const string DC_SongName = "SongName",
                             DC_SongId = "SonyId",
                             DC_SongNum = "SonyName",
                             DC_ArtistName = "ArtName",
                             DC_AlbumName = "AlbumName",
                             DC_AlbumMemo = "AlbumMemo",
                             DC_ArtistId = "ArtId",
                             DC_SongSize="SongSize",DC_SongFormat="SongFormat",
                             DC_AlbumId = "AlbumId";

        private DataView m_CurrAlbums, m_CurrArtists, m_CurrAllSong;

        public string DownSong(string sourceUrl, string filePath)
        {
            return DownloadFile(sourceUrl, filePath);

            //System.Diagnostics.Process.Start("IEXPLORE.EXE", sourceUrl);
            //return "Error";
        }


        public string DownloadFile(string url, string filePath)
        {
            string reMsg = "";
            Stream st = null, so = null;
            WebResponse myrp = null;
            var Myrq = (HttpWebRequest) WebRequest.Create(url);
            var swErr = new StreamWriter("ErrDownUrl_["+DateTime.Now.ToString("yyyyMMddhhmmss")+"].txt",false,Encoding.UTF8);
            try
            {
                myrp = Myrq.GetResponse();
                long totalBytes = myrp.ContentLength;
                if (myrp.ContentLength != 0)
                {
                    // MessageBox.Show("文件存在");
                    st = myrp.GetResponseStream();
                    so = new FileStream(filePath,
                                        FileMode.Create);
                    long totalDownloadedByte = 0;
                    var by = new byte[1024];
                    int osize = st.Read(by, 0, by.Length);
                    while (osize > 0)
                    {
                        totalDownloadedByte = osize + totalDownloadedByte;
                        so.Write(by, 0, osize);
                        osize = st.Read(by, 0, by.Length);
                    }
                }
            }
            catch (Exception ex)
            {
                reMsg = url + "\r\n" + ex.Message;
                swErr.WriteLine(m_CurrSongPageUrl + "\r\n\r\n" + url + "\r\n\r\n" + filePath);
            }
            finally
            {
                if (so != null) so.Close();
                if (st != null) st.Close();
                if (myrp != null) myrp.Close();
                swErr.Close();
            }
            return reMsg;
        }


        public HtmlDocument GetHtmlDocmentByUrl(string urlStr, bool isReplaceInHis)
        {
            var myReq = (HttpWebRequest) WebRequest.Create(urlStr);
            var myResp = (HttpWebResponse) myReq.GetResponse();
            Stream rStream = myResp.GetResponseStream();
            if (rStream == null) return null;
            var respStream = new StreamReader(rStream, Encoding.UTF8);
            string strhtml;
            try
            {
                strhtml = respStream.ReadToEnd();
            }
            finally
            {
                respStream.Dispose();
                respStream.Close();
                myResp.Close();
            }
            if (string.IsNullOrEmpty(strhtml)) return null;
            wb.Navigate("about:blank");
            wb.Document.OpenNew(isReplaceInHis);
            wb.Document.Write(strhtml);
            return wb.Document;
        }

        public HtmlDocument GetHtmlDocmentByUrl(string urlStr)
        {
            return GetHtmlDocmentByUrl(urlStr, false);
        }

        public HtmlDocument GetHtmlDocmentByUrl_2(string urlStr)
        {
            wb.Navigate(urlStr);
            while (wb.IsBusy) Thread.Sleep(200);
            if (wb.Document == null) return null;
            wb.Document.OpenNew(true);
            return wb.Document;
        }

        public string InitArtisInfos(Hashtable htUrls)
        {
            var sbReVal = new StringBuilder();

            var sb = new StringBuilder();
            foreach (string groupName in htUrls.Keys)
            {
                if (sbReVal.Length > 0)
                {
                    sbReVal.Append("\r\n");
                    Thread.Sleep(2000);
                }
                sbReVal.Append(groupName);
                string strUrl = htUrls[groupName].ToString();
                HtmlDocument doc = GetHtmlDocmentByUrl(strUrl);
                if (doc == null)
                {
                    sbReVal.Append("数据加载失败");
                    continue;
                }
                HtmlElementCollection el = doc.GetElementsByTagName("a");

                const string strStartsWith = "<a href=\"/artist/info.php?singerid=";
                string startsWithLowerStr = strStartsWith.ToLower();
                foreach (HtmlElement e in el)
                {
                    string str = e.OuterHtml;
                    string strLower = str.ToLower();
                    if (strLower.StartsWith(startsWithLowerStr) && e.InnerText != null && e.Parent!=null && e.Parent.TagName.ToLower() == "li")
                    {
                        str = str.Remove(0, strStartsWith.Length);
                        int tempIndex = str.IndexOf('"');
                        if (tempIndex > -1)
                        {
                            string strArtId = str.Substring(0, tempIndex);
                            string strArtName = e.InnerText;
                            sb.Append(strArtId + FG_VALUE + strArtName + FG_VALUE + groupName + "\r\n");
                        }
                    }
                }
                sbReVal.Append("数据加载成功");
            }
            if (sb.Length > 0)
            {
                var sw = new StreamWriter(FP_ART_INFO, false, Encoding.UTF8);
                try
                {
                    sw.Write(sb);
                }
                finally
                {
                    sw.Dispose();
                    sw.Close();
                }
            }
            return sbReVal.ToString();
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            string msg = InitArtisInfos(new Hashtable
                                            {
                                                {
                                                    "港台女歌手",
                                                    "http://www.top100.cn/artist/index.php?s=w&area=hktw"
                                                    }
                                                ,
                                                {
                                                    "港台男歌手",
                                                    "http://www.top100.cn/artist/index.php?s=m&area=hktw"
                                                    }
                                                ,
                                                {
                                                    "港台组合",
                                                    "http://www.top100.cn/artist/index.php?s=l&area=hktw"
                                                    }
                                            });
            MessageBox.Show(msg);
        }

        private void SetArtistsInfo(string filterString)
        {
            var dt = new DataTable("ArtInfos");
            dt.Columns.Add("Id", typeof (string));
            dt.Columns.Add("Name", typeof (string));
            dt.Columns.Add("GroupName", typeof (string));

            var sr = new StreamReader(FP_ART_INFO);
            try
            {
                while (sr.Peek() > 0)
                {
                    string rowContext = sr.ReadLine();
                    if (rowContext == null) continue;
                    string[] ss = rowContext.Split(FG_VALUE);
                    if (ss.Length > 2)
                    {
                        dt.Rows.Add(dt.NewRow().ItemArray = new[] {ss[0], ss[1], ss[2]});
                    }
                }
            }
            finally
            {
                sr.Dispose();
                sr.Close();
            }
            DataView dv = dt.DefaultView;
            dv.RowFilter = filterString;
            m_CurrArtists = dv;
        }

        private DataView GetAllSongInfos(string filterString)
        {
            HtmlDocument doc = GetHtmlDocmentByUrl("http://www.top100.cn/search/?act=allsong&keyword=" + filterString);
            HtmlElementCollection elAs = doc.GetElementsByTagName("ul");
            var dt = new DataTable("AllSongInfos");

            dt.Columns.Add(DC_SongId, typeof(string));
            dt.Columns.Add(DC_SongName, typeof(string));
            //dt.Columns.Add(DC_ArtistId, typeof(string));
            dt.Columns.Add(DC_ArtistName, typeof(string));
            //dt.Columns.Add(DC_AlbumId, typeof(string));
            dt.Columns.Add(DC_AlbumName, typeof(string));

            

            foreach (HtmlElement ela in elAs)
            {
                if( ela.GetAttribute("ClassName") == "top100list clearfix" && ela.Children.Count > 5)
                {
                    var tempRow = dt.NewRow();
                    var tempHref = ela.Children[2].Children[0].GetAttribute("href");
                    if (string.IsNullOrEmpty(tempHref)) continue;
                    tempRow[DC_SongId] = tempHref.Substring(tempHref.IndexOf("song=") + 5);
                    tempRow[DC_SongName] = ela.Children[2].Children[0].GetAttribute("title");
                    tempHref = ela.Children[3].Children[0].GetAttribute("href");
                    //var artId = tempHref.Substring(tempHref.IndexOf("info-") + 5);
                    //artId = artId.Substring(0, artId.LastIndexOf("."));
                    //tempRow[DC_ArtistId] = artId;
                    tempRow[DC_ArtistName] = ela.Children[3].Children[0].GetAttribute("title");
                    tempHref = ela.Children[6].Children[0].GetAttribute("href");
                    //var albumId = tempHref.Substring(tempHref.IndexOf("('") + 2);
                    //tempRow[DC_AlbumId] = albumId.Substring(0, albumId.IndexOf("')"));
                    tempRow[DC_AlbumName] = ela.Children[4].Children[0].GetAttribute("title");
                    dt.Rows.Add(tempRow);
                }
            }
            return dt.DefaultView;
        }

        private void SetDataViewToList(DataView dv)
        {
            if (dv == null) return;
            dvList.DataSource = dv;
            dvList.Show();
            cmsForDv.Items[0].Enabled = true;
            cmsForDv.Items[2].Enabled = cmsForDv.Items[1].Enabled = false;
        }

        private void SetDataView(string filterString)
        {
            SetArtistsInfo(filterString);
            SetDataViewToList(m_CurrArtists);
        }

        private void btnFilter_Click(object sender, EventArgs e)
        {
            if(txtArtist.Text.Length == 0)
            {
                MessageBox.Show("筛选条件不能为空");
                return;
            }
            dvList.DataSource = GetAllSongInfos(txtArtist.Text);
        }

        private string GetCurrFirstCellVal(string colName)
        {
            if (dvList.CurrentRow == null) return "";
            DataGridViewRow row = dvList.CurrentRow;
            string strId = Convert.ToString(row.Cells[colName].Value);
            return strId;
        }

        private DataView GetAlbumsInfoByArtId(string artId)
        {
            //<li class="No2" style="width:250px;"><a title="等你等到我心痛" href="http://www.top100.cn/song/?song=jwadyc3tgo3d1cb1go" target=_blank style="overflow:hidden;display:block;height:30px;width:250px;">等你等到我心痛</a>
            //http://www.top100.cn/album/list.php?singerid=309
            //<A HREF=/album/list.php?singerid=309&amp;pages=13>尾页</A>
            HtmlDocument doc = GetHtmlDocmentByUrl("http://www.top100.cn/album/list.php?singerid="+artId);
            HtmlElementCollection elAs = doc.GetElementsByTagName("a");
            var dt = new DataTable("ArtAlbumInfos");

            dt.Columns.Add(DC_AlbumId, typeof (string));
            dt.Columns.Add(DC_AlbumName, typeof (string));
            dt.Columns.Add(DC_AlbumMemo, typeof (string));
            dt.Columns.Add(DC_ArtistId, typeof (string));

            foreach (HtmlElement ela in elAs)
            {
                if (ela.GetAttribute("ClassName") == "Listen_point right")
                {
                    if (ela.Parent == null) continue;
                    var strAlbumId = ela.GetAttribute("href");
                    var tempNode = ela.Parent;
                    if (tempNode.TagName.ToLower() != "dd" && tempNode.Children.Count < 2) continue;
                    if (tempNode.Children[0].TagName.ToLower() != "div") continue;
                    var strAlbumName = tempNode.Children[0].InnerText;
                    var strAlbumMemo = "";
                    if (tempNode.NextSibling != null && tempNode.NextSibling.TagName.ToLower() == "dd")
                        strAlbumMemo = tempNode.NextSibling.InnerText;
                    dt.Rows.Add(dt.NewRow().ItemArray = new[] { strAlbumId, strAlbumName, strAlbumMemo, artId });
                }
            }
            m_CurrAlbums = dt.DefaultView;
            return dt.DefaultView;
        }

        private void iAlbums_Click(object sender, EventArgs e)
        {
            dvList.DataSource = GetAlbumsInfoByArtId(GetCurrFirstCellVal(DC_ArtistId));
            dvList.Show();
            cmsForDv.Items[2].Enabled = cmsForDv.Items[1].Enabled = true;
            cmsForDv.Items[0].Enabled = false;
        }

        private string GetNextNodeInnerText(ref HtmlElement curr, string classNameFilter)
        {
            string reVal = "";
            HtmlElement tempTd = curr.NextSibling;
            if (tempTd != null && tempTd.GetAttribute("ClassName") == classNameFilter)
            {
                reVal = tempTd.InnerText;
                curr = tempTd;
            }
            return reVal;
        }

        private DataView GetSonysInfoByAlbumId(string strAlbumId,string albumName)
        {
            /*
             <ul class="Listen_downloadtop2 clearfix">
        	<li class="No1"><a href="/album/info.php?albumid=31430" target="_blank"><img src="http://pic.top100.cn/SpecialImg/4/middle_special_31430.jpg" width="110" height="110" /></a></li>
            <li class="No2"><a href="javascript:page.common.openPlayer('mjwadyc3tgo3uycbo8r');">吻别</a></li>
            <li class="No3"><a href='/artist/info-agcad1.shtml' title='张学友' target='_blank'>张学友</a>&nbsp;</li>
            <li class="No4">7,035 KB</li>
            <li class="No5">MP3</li>
            <li class="No6"><a href="/download/dl.php?n=%E5%90%BB%E5%88%AB.mp3&al=sgcauec3o"><img src="../style/img/btn_listendownload.gif" width="65" height="19" /></a></li>
        	</ul>
             */
            //strAlbumId = "kcadyctugahuncbogy";
            HtmlDocument doc = GetHtmlDocmentByUrl("http://www.top100.cn/download/download.php?Productid=" + strAlbumId);
            HtmlElementCollection elAs = doc.GetElementsByTagName("ul");
            var dt = new DataTable("AlbumSongInfos");
            dt.Columns.Add(DC_SongName, typeof (string));
            dt.Columns.Add(DC_SongSize, typeof(string));
            dt.Columns.Add(DC_SongFormat, typeof(string));
            dt.Columns.Add(DC_ArtistName, typeof (string));
            dt.Columns.Add(DC_AlbumName, typeof (string));
            foreach (HtmlElement ela in elAs)
            {
                if (ela.GetAttribute("ClassName") == "Listen_downloadtop2 clearfix" && ela.Children.Count > 5)
                {
                    var row = dt.NewRow();
                    row[DC_SongName] = ela.Children[1].InnerText;
                    row[DC_ArtistName] = ela.Children[2].InnerText;
                    row[DC_SongSize] = ela.Children[3].InnerText;
                    row[DC_SongFormat] = ela.Children[4].InnerText;
                    row[DC_AlbumName] = albumName;
                    dt.Rows.Add(row);
                }
            }
            return dt.DefaultView;
        }

        private string GetSonyDownUrl(string songId)
        {
            //http://g.top100.cn/16667639/html/download.html?id=Sc2f4eff9ea7be909
            //http://www.google.cn/music/top100/musicdownload?id=Sc2f4eff9ea7be909
            string trgUrl = "";
            string songPageUrl = "http://www.top100.cn/download/download.php?Productid=" + songId;
            HtmlDocument doc = GetHtmlDocmentByUrl(songPageUrl, true);
            HtmlElementCollection els = doc.GetElementsByTagName("li");
            var sb = new StringBuilder();
            foreach (HtmlElement ela in els)
            {
                
                if (ela.GetAttribute("ClassName").StartsWith("No6"))
                {
                    
                    if (ela.Children.Count > 0 && ela.Children[0].TagName.ToLower() == "a")
                    {
                        string herfVal = ela.Children[0].GetAttribute("href");
                        int iEnd = herfVal.IndexOf("&");
                        int iStart = herfVal.ToLower().IndexOf("about:/");
                        if (iEnd > iStart && iStart > -1)
                            trgUrl = herfVal.Substring(iStart).Replace("about:/", "http://www.top100.cn/");
                    }
                }

                sb.Append(ela.OuterHtml);
                sb.Append("\r\n\r\n");
            }
            return trgUrl;
        }

        private void iSongs_Click(object sender, EventArgs e)
        {
            dvList.DataSource = GetAllSongInfos(GetCurrFirstCellVal(DC_AlbumName));
            dvList.Show();
            //cmsForDv.Items[0].Enabled = cmsForDv.Items[2].Enabled = cmsForDv.Items[1].Enabled = false;
        }

        private void iDownload_Click(object sender, EventArgs e)
        {
            DataView dv = GetAllSongInfos(GetCurrFirstCellVal(DC_AlbumName));
            if (dv == null) return;
            DataTable dt = dv.Table;
            var sb = new StringBuilder();
            foreach (DataRow r in dt.Rows)
            {
                string songId = Convert.ToString(r[DC_SongId]);
                string songName = Convert.ToString(r[DC_SongName]);
                string artName = Convert.ToString(r[DC_ArtistName]);
                string albumName = Convert.ToString(r[DC_AlbumName]);
                string trgUrl = (GetSonyDownUrl(songId));
                //if (trgUrl.Length > 0) Thread.Sleep(2000);
                if (trgUrl.Length > 0)
                {
                    string strPath = "C:\\";
                    string strFileName = artName + "." + albumName  + " - " + songName + ".mp3";
                    strPath += "\\Top100_Down";
                    if (!Directory.Exists(strPath)) Directory.CreateDirectory(strPath);
                    strPath += "\\"+artName;
                    if (!Directory.Exists(strPath)) Directory.CreateDirectory(strPath);
                    strPath += "\\" + albumName;
                    if (!Directory.Exists(strPath)) Directory.CreateDirectory(strPath);
                    strPath += "\\" + strFileName;
                    string errMsg = DownSong(trgUrl, strPath);
                    if (errMsg.Length > 0)
                    {
                        sb.Append(m_CurrSongPageUrl + "\r\n\r\n" + strFileName + "\r\n" + errMsg + "\r\n\r\n");
                        break;
                    }
                    Thread.Sleep(6000);
                }
            }
            MessageBox.Show(sb.ToString());
        }

        private void btnCurrAlbum_Click(object sender, EventArgs e)
        {
            SetDataViewToList(m_CurrAlbums);
            //cmsForDv.Items[2].Enabled = cmsForDv.Items[1].Enabled = true;
            //cmsForDv.Items[0].Enabled = false;
        }

        private void btnNext_Click(object sender, EventArgs e)
        {

        }
    }
}
